home *** CD-ROM | disk | FTP | other *** search
/ Mac Mania 5 / MacMania 5.toast / / Internet software / NewsWatcher / NW Source / Source / binmandlg.c < prev    next >
Text File  |  1997-01-09  |  12KB  |  441 lines

  1. /*----------------------------------------------------------------------------
  2.  
  3.     binmandlg.c
  4.  
  5.     This module presents the extract binaries manually dialog.
  6.     
  7.     Copyright © 1994-1997, Northwestern University.
  8.  
  9. ----------------------------------------------------------------------------*/
  10.  
  11. #include <string.h>
  12. #include <stdio.h>
  13. #include <ctype.h>
  14. #include <stdlib.h>
  15.  
  16. #include "glob.h"
  17. #include "binmandlg.h"
  18. #include "biglist.h"
  19. #include "strutil.h"
  20. #include "drawutil.h"
  21. #include "olddrag.h"
  22. #include "dialog.h"
  23. #include "memutil.h"
  24. #include "newswatcher.h"
  25.  
  26.  
  27.  
  28. #define kExtractBinariesManuallyDlg            149
  29. #define kLabelItem                            3
  30. #define kListItem                            4
  31.  
  32.  
  33.  
  34. static BigListRef gList;
  35. static TSubject **gSubjectArray;
  36. static Handle gStrings;
  37. static short gDragTarget;
  38. static DragTrackingHandlerUPP gHandleTrackingUPP = nil;
  39. static DragReceiveHandlerUPP gHandleReceiveUPP = nil;
  40. static ModalFilterUPP gMyDialogFilterUPP = nil;
  41. static UserItemUPP gDlgLabelUserItemUPP = nil;
  42. static UserItemUPP gDlgListUserItemUPP = nil;
  43.  
  44.  
  45.  
  46. /*----------------------------------------------------------------------------
  47.     DrawItem
  48.     
  49.     Draw one list item in the dialog.
  50.     
  51.     Entry:    theList = list ref = gList.
  52.             index = index of info in gSubjectArray.
  53.             *itemRect = item rectangle.  
  54. ----------------------------------------------------------------------------*/
  55.  
  56. static void DrawItem (BigListRef theList, long index, Rect *itemRect)
  57. {
  58.     Str255 str;
  59.     CStr255 subject;
  60.     FontInfo fontInfo;
  61.     
  62.     strcpy(subject, *gStrings + (*gSubjectArray)[index].subjectOffset);
  63.     sprintf((char*)str, "%ld - %.240s", (*gSubjectArray)[index].number, subject);
  64.     c2pstr((char*)str);
  65.     TruncString(itemRect->right - itemRect->left, str, smTruncEnd);
  66.     GetFontInfo(&fontInfo);
  67.     MoveTo(itemRect->left, itemRect->top + fontInfo.ascent);
  68.     DrawString(str);
  69. }
  70.  
  71.  
  72.  
  73. /*----------------------------------------------------------------------------
  74.     DlgLabelUserItem
  75.     
  76.     A user item procedure to draw the label at the top of the dialg.
  77.     
  78.     Entry:    dlg = pointer to dialog.
  79.             item = item number.
  80. ----------------------------------------------------------------------------*/
  81.  
  82. static pascal void DlgLabelUserItem (DialogPtr dlg, short item)
  83. {
  84.     Str255 label;
  85.     Handle itemHandle;
  86.     short itemType;
  87.     Rect box;
  88.     TextStyle savedStyle;
  89.  
  90.     GetDialogItem(dlg, item, &itemType, &itemHandle, &box);
  91.     GetPString(kStrExtractBinariesManuallyDlgLabel, label);
  92.     GetPortTextStyle(&savedStyle);
  93.     TextFont(systemFont);
  94.     TextSize(12);
  95.     TETextBox(label+1, label[0], &box, teForceLeft);
  96.     SetPortTextStyle(&savedStyle);
  97. }
  98.  
  99.  
  100.  
  101. /*----------------------------------------------------------------------------
  102.     DlgListUserItem
  103.     
  104.     A user item procedure to draw the list in the dialog.
  105.     
  106.     Entry:    dlg = pointer to dialog.
  107.             item = item number.
  108. ----------------------------------------------------------------------------*/
  109.  
  110. static pascal void DlgListUserItem (DialogPtr dlg, short item)
  111. {
  112.     Handle itemHandle;
  113.     short itemType;
  114.     Rect box;
  115.  
  116.     GetDialogItem(dlg, item, &itemType, &itemHandle, &box);
  117.     FrameRect(&box);
  118.     BigLGetViewRect(gList, &box);
  119.     box.right -= 15;
  120.     EraseRect(&box);
  121.     BigLUpdate(gList);
  122. }
  123.  
  124.  
  125.  
  126. /*----------------------------------------------------------------------------
  127.     MyDialogFilter 
  128.     
  129.     Our dialog filter.
  130.         
  131.     Entry:    dlg = pointer to dialog.
  132.             ev = pointer to event record.
  133.             
  134.     Exit:    function result = true if event handled and item hit.
  135.             *itemHit = item number of item hit.
  136.             ev = pointer to possibly modified event record.
  137. ----------------------------------------------------------------------------*/
  138.  
  139. static pascal Boolean MyDialogFilter (DialogPtr dlg, 
  140.     EventRecord *ev, short *itemHit)
  141. {
  142.     short itemType;
  143.     Handle itemHandle;
  144.     Rect box;
  145.     Point where;
  146.     Boolean doubleClick;
  147.  
  148.     if (ev->what == mouseDown) {
  149.         GetDialogItem(dlg, kListItem, &itemType, &itemHandle, &box);
  150.         InsetRect(&box, 1, 1);
  151.         where = ev->where;
  152.         GlobalToLocal(&where);
  153.         if (PtInRect(where, &box)) {
  154.             BigLClick(gList, where, ev->modifiers, &doubleClick);
  155.             ev->what = nullEvent;
  156.             return false;
  157.         }
  158.     } else if (ev->what == keyDown || ev->what == autoKey) {
  159.         if (BigLKey(gList, ev->message & charCodeMask, ev->modifiers)) {
  160.             ev->what = nullEvent;
  161.             return false;
  162.         }
  163.     }
  164.     return DialogFilter(dlg, ev, itemHit);
  165. }
  166.  
  167.  
  168.  
  169. /*----------------------------------------------------------------------------
  170.     ClickLoop
  171.     
  172.     The click loop function for the list. It initiates item drags.
  173.     
  174.     Entry:    theList = list ref = gList.
  175.             where = mouse location, in local coords.
  176.             modifiers = modifiers field from event record.
  177.             helperItem = 
  178.                 for shift-click, the item number of the item at the
  179.                     other end of the selection range from the initially 
  180.                     clicked item (the "anchor" item for a shift-drag).
  181.                 otherwise, the item number of the initially clicked item.
  182.             
  183.     Exit:    function result = error code.
  184. ----------------------------------------------------------------------------*/
  185.  
  186. static OSErr ClickLoop (BigListRef theList, Point where, short modifiers,
  187.     long helperItem)
  188. {    
  189.     OSErr err = noErr;
  190.     DragReference dragRef;
  191.     Boolean haveDragRef = false;
  192.     RgnHandle dragRgn = nil;
  193.     EventRecord ev;
  194.     
  195.     if ((modifiers & shiftKey) != 0 || (modifiers & cmdKey) != 0) {
  196.         return BigLDefaultClickLoop(theList, where, modifiers, helperItem);
  197.     }
  198.     
  199.     LocalToGlobal(&where);
  200.     if (WaitMouseMoved(where)) {
  201.         err = NewDrag(&dragRef);
  202.         if (err != noErr) goto exit;
  203.         haveDragRef = true;
  204.         err = AddDragItemFlavor(dragRef, 1, kNewsWatcherSignature, 
  205.             nil, 0, flavorSenderOnly);
  206.         if (err != noErr) goto exit;
  207.         BigLBuildSelectedItemsDragRegion(theList, &dragRgn);
  208.         gDragTarget = -1;
  209.         ev.what = mouseDown;
  210.         ev.message = 0;
  211.         ev.when = TickCount();
  212.         ev.where = where;
  213.         ev.modifiers = 0;
  214.         err = TrackDrag(dragRef, &ev, dragRgn);
  215.         if (err != noErr) goto exit;
  216.         DisposeRgn(dragRgn);
  217.         DisposeDrag(dragRef);
  218.     }
  219.     
  220.     return noErr;
  221.     
  222. exit:
  223.  
  224.     if (dragRgn != nil) DisposeRgn(dragRgn);
  225.     if (haveDragRef) DisposeDrag(dragRef);
  226.     return err;
  227. }
  228.  
  229.  
  230.  
  231. /*----------------------------------------------------------------------------
  232.     HandleTracking 
  233.     
  234.     Drag Manager tracking handler for the dialog.
  235.     
  236.     Entry:    message = tracking message from Drag Manager.
  237.             wind = pointer to dialog.
  238.             handlerRefCon = reference constant (nil).
  239.             theDrag = drag reference.
  240.             
  241.     Exit:    function result = error code.
  242. ----------------------------------------------------------------------------*/
  243.  
  244. static pascal OSErr HandleTracking (DragTrackingMessage message,
  245.     WindowPtr wind, void *handlerRefCon, DragReference theDrag)
  246. {
  247.     Rect rView, contentRect;
  248.     Point where;
  249.     static Boolean canAcceptDrag;
  250.     OSErr err = noErr;
  251.     DragAttributes attributes;
  252.     
  253.     GetDragAttributes(theDrag, &attributes);
  254.     if ((attributes & dragInsideSenderApplication) == 0) return noErr;
  255.     
  256.     switch (message) {
  257.             
  258.         case dragTrackingInWindow:
  259.         
  260.             BigLGetViewRect(gList, &rView);
  261.             SetRect(&contentRect, rView.left, 0, rView.right-15, rView.bottom+15);    
  262.             GetDragMouse(theDrag, &where, nil);
  263.             GlobalToLocal(&where);
  264.             if (PtInRect(where, &contentRect)) {
  265.                 err = BigLHandleDragTracking(gList, theDrag, where);
  266.                 if (err != noErr) goto exit;;
  267.             } else {
  268.                 BigLTerminateDragTracking(gList, theDrag);
  269.             }
  270.             break;
  271.             
  272.         case dragTrackingLeaveWindow:
  273.         
  274.             BigLTerminateDragTracking(gList, theDrag);
  275.             break;
  276.             
  277.     }
  278.  
  279.     return noErr;
  280.     
  281. exit:
  282.  
  283.     BigLTerminateDragTracking(gList, theDrag);
  284.     gDragErr = err;
  285.     return err;
  286. }
  287.  
  288.  
  289.  
  290. /*----------------------------------------------------------------------------
  291.     HandleReceive 
  292.     
  293.     Drag Manager receive handler for the dialog.
  294.     
  295.     Entry:    wind = pointer to dialog.
  296.             handlerRefCon = reference constant (nil).
  297.             theDrag = drag reference.
  298.             
  299.     Exit:    function result = error code.
  300.     
  301.     Note: No user interaction or network transactions are permitted in
  302.     this function.
  303. ----------------------------------------------------------------------------*/
  304.  
  305. static pascal OSErr HandleReceive (WindowPtr wind, 
  306.     void *handlerRefCon, DragReference theDrag)
  307. {
  308.     gDragTarget = BigLTerminateDragTracking(gList, theDrag);
  309.     if (gDragTarget < 0) return dragNotAcceptedErr;
  310.     return BigLMoveSelectedItems(gList, gList, gDragTarget, nil);
  311. }
  312.  
  313.  
  314.  
  315. /*----------------------------------------------------------------------------
  316.     DoExtractBinariesManuallyDialog
  317.     
  318.     Present the "Extract Binaries Manually" dialog.
  319.             
  320.     Entry:    wind = pointer to subject window.
  321.     
  322.     Exit:    function result = error code.
  323.             *articleList = handle to array of longword article numbers.
  324. ----------------------------------------------------------------------------*/
  325.  
  326. OSErr DoExtractBinariesManuallyDialog (WindowPtr wind, long ***articleList)
  327. {
  328.     TWindow **info;
  329.     BigListRef subjectList;
  330.     long numSelected = 0, itema, itemb, index;
  331.     OSErr err = noErr;
  332.     DialogPtr dlg = nil;
  333.     short itemHit, fontNum, itemType, itemHeight, listHeight;
  334.     Handle itemHandle;
  335.     Rect rView;
  336.     long **artList = nil;
  337.     Boolean savedHiliteState;
  338.     
  339.     if (gMyDialogFilterUPP == nil) gMyDialogFilterUPP =
  340.         NewModalFilterProc(MyDialogFilter);
  341.     if (gDlgLabelUserItemUPP == nil) gDlgLabelUserItemUPP =
  342.         NewUserItemProc(DlgLabelUserItem);
  343.     if (gDlgListUserItemUPP == nil) gDlgListUserItemUPP =
  344.         NewUserItemProc(DlgListUserItem);
  345.     
  346.     gList = nil;
  347.     
  348.     info = (TWindow**) GetWRefCon(wind);
  349.     subjectList = (**info).subjectList;
  350.     gSubjectArray = (**info).subjectArray;
  351.     gStrings = (**info).strings;
  352.  
  353.     err = MyGetNewDialog(kExtractBinariesManuallyDlg, ok, cancel, &dlg);
  354.     if (err != noErr) return err;
  355.     DlgSetUserItem(dlg, kLabelItem, gDlgLabelUserItemUPP);
  356.     DlgSetUserItem(dlg, kListItem, gDlgListUserItemUPP);
  357.         
  358.     if (gHaveDragMgr) {
  359.         if (gHandleTrackingUPP == nil) gHandleTrackingUPP =
  360.             NewDragTrackingHandlerProc(HandleTracking);
  361.         if (gHandleReceiveUPP == nil) gHandleReceiveUPP =
  362.             NewDragReceiveHandlerProc(HandleReceive);
  363.         err = InstallTrackingHandler(gHandleTrackingUPP, dlg, nil);
  364.         if (err != noErr) goto exit;
  365.         err = InstallReceiveHandler(gHandleReceiveUPP, dlg, nil);
  366.         if (err != noErr) goto exit;
  367.     }
  368.     
  369.     SetPort(dlg);
  370.     
  371.     GetFontNumber("\pMonaco", &fontNum);
  372.     TextFont(fontNum);
  373.     TextSize(9);
  374.     
  375.     GetDialogItem(dlg, kListItem, &itemType, &itemHandle, &rView);
  376.     InsetRect(&rView, 1, 1);
  377.     itemHeight = GetFontLineHeight(dlg);
  378.     listHeight = rView.bottom - rView.top;
  379.     listHeight = listHeight/itemHeight*itemHeight;
  380.     rView.bottom = rView.top + listHeight;
  381.     savedHiliteState = ((WindowPeek)dlg)->hilited;
  382.     ((WindowPeek)dlg)->hilited = true;
  383.     err = BigLNew(&rView, dlg, itemHeight, true, DrawItem, &gList);
  384.     ((WindowPeek)dlg)->hilited = savedHiliteState;
  385.     if (err != noErr) goto exit;
  386.     BigLSetClickLoop(gList, gHaveDragMgr ? ClickLoop : OldExtractBinariesManuallyClickLoop);
  387.     InsetRect(&rView, -1, -1);
  388.     SetDialogItem(dlg, kListItem, itemType, itemHandle, &rView);
  389.     
  390.     numSelected = BigLGetNumSelectedItems(subjectList);    
  391.     err = BigLAddItems(gList, 0, numSelected);
  392.     if (err != noErr) goto exit;
  393.     
  394.     itema = BigLGetFirstSelectedItem(subjectList);
  395.     itemb = 0;
  396.     while (itema >= 0) {
  397.         index = BigLGetData(subjectList, itema);
  398.         BigLSetData(gList, itemb, index);
  399.         itemb++;
  400.         itema = BigLGetNextSelectedItem(subjectList, itema+1);
  401.     }
  402.     
  403.     MyModalDialog(dlg, gMyDialogFilterUPP, &itemHit);
  404.     
  405.     if (itemHit == ok) {
  406.         err = MyNewHandle(numSelected * sizeof(long), &artList);
  407.         if (err != noErr) goto exit;
  408.         for (itemb = 0; itemb < numSelected; itemb++) {
  409.             index = BigLGetData(gList, itemb);
  410.             (*artList)[itemb] = (*gSubjectArray)[index].number;
  411.         }
  412.     }
  413.     
  414.     BigLDispose(gList);
  415.     gList = nil;
  416.     
  417.     if (gHaveDragMgr) {
  418.         RemoveTrackingHandler(gHandleTrackingUPP, dlg);
  419.         RemoveReceiveHandler(gHandleReceiveUPP, dlg);
  420.     }
  421.     
  422.     err = DoClose(dlg);
  423.     if (err != noErr) return err;
  424.     if (itemHit == cancel) return userCanceledErr;
  425.     
  426.     *articleList = artList;
  427.     return noErr;
  428.     
  429. exit:
  430.  
  431.     if (gList != nil) BigLDispose(gList);
  432.     gList = nil;
  433.     if (dlg != nil) {
  434.         RemoveTrackingHandler(gHandleTrackingUPP, dlg);
  435.         RemoveReceiveHandler(gHandleReceiveUPP, dlg);
  436.         DoClose(dlg);
  437.     }
  438.     MyDisposeHandle(artList);
  439.     return err;
  440. }
  441.